package main

import (
	"database/sql/driver"
	"encoding/json"
	"errors"
	"flag"
	"fmt"
	"github.com/xuri/excelize/v2"
	"go_learn/utils"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"log"
	"strconv"
	"strings"
	"time"
)

type JSON json.RawMessage

type MysqlConfig map[string]string
type DealConfig map[string][]int64

var config = MysqlConfig{}
var dealIds = DealConfig{}
var virtualCardIds []string
var env string

func init() {
	flag.StringVar(&env, "env", "", "环境变量")
	env = strings.ToLower(env)
	flag.Parse()
	config["prod-ios"] = "root:12345678@(rds-ios-slave.czuijwtvmv6c.ap-east-1.rds.amazonaws.com:3306)/game_log"
	config["prod-andr"] = "root:12345678@(rds-adr-slave.czuijwtvmv6c.ap-east-1.rds.amazonaws.com:3306)/game_log"
	config["local"] = "root:123456@(localhost:3306)/yhhy?charset=utf8mb4&parseTime=True"
	config["dev-ios"] = "lurendou:lurendou520@(localhost:3306)/yhhy?charset=utf8mb4&parseTime=True"

	dealIds["prod-ios"] = []int64{644, 645, 646}
	dealIds["prod-andr"] = []int64{680, 681, 682}
	dealIds["local"] = []int64{}

	virtualCardIds = []string{"1014101201", "1014101601", "1014102201", "1014102601", "1014103801", "1014104001", "1014104401", "1014104801", "1014105201"}
}

func initMysql() *gorm.DB {
	uri, ok := config[env]
	if !ok {
		panic("failed config env")
	}
	db, err := gorm.Open(mysql.Open(uri), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}
	sqlDB, err := db.DB()
	if err != nil {
		panic("connect db server failed")
	}
	sqlDB.SetConnMaxLifetime(600 * time.Second)
	sqlDB.SetMaxOpenConns(50)
	sqlDB.SetMaxIdleConns(10)
	return db
}

type Information struct {
	SrcType     string `json:"srctype"`
	SrcIp       string `json:"src_ip"`
	ReceiveTime string `json:"receive_time"`
	RoleId      string `json:"roleid"`
	ActivityId  string `json:"activity_id"`
	RewardInfo  string `json:"reward_info"`
}

type InformationOrder struct {
	SrcType     string  `json:"srctype"`
	SrcIp       string  `json:"src_ip"`
	ReceiveTime string  `json:"receive_time"`
	RoleId      string  `json:"roleid"`
	LogInfo     LogInfo `json:"logInfo"`
}

type VirtualCard struct {
	SrcType       string `json:"srctype"`
	SrcIp         string `json:"src_ip"`
	ReceiveTime   string `json:"receive_time"`
	RoleId        string `json:"roleid"`
	VirtualCardId string `json:"virtual_card_id"`
}

type LogInfo struct {
	OrderId string `json:"orderid"`
	DealId  int64  `json:"dealid"`
}

type Log struct {
	Id          int64     `gorm:"primaryKey"`
	RoleId      int64     `gorm:"column:_roleid"`
	Tag         string    `gorm:"column:_tag"`
	Information JSON      `gorm:"column:_infomation" sql:"type:json"`
	CreatedAt   time.Time `gorm:"column:created_at"`
}

// Value 从输入转化为JSON，特殊字段
func (i Information) Value() (driver.Value, error) {
	b, err := json.Marshal(i)
	return string(b), err
}

// Value 从输入转化为JSON
func (j JSON) Value() (driver.Value, error) {
	if len(j) == 0 {
		return nil, nil
	}
	return json.RawMessage(j).MarshalJSON()
}

// Scan 从数据库JSON字段转换为model对应JSON字段
func (j *JSON) Scan(value interface{}) error {
	bytes, ok := value.([]byte)
	if !ok {
		return errors.New(fmt.Sprint("Failed to unmarshal JSONB value:", value))
	}

	result := json.RawMessage{}
	err := json.Unmarshal(bytes, &result)
	*j = JSON(result)
	return err
}

func (Log) TableName() string {
	return "log"
}

var tag string

func main() {
	start := time.Now().Add(-(24 * time.Hour)).Format("2006-01-02 00:00:00")
	end := time.Now().Format("2006-01-02 00:00:00")
	tag = "ADD_ORDER"

	start = "2022-05-26 00:00:00"
	end = "2022-05-31 00:00:00"
	tag = "GRT_VIRTUAL_CARD"

	var logs []Log
	db := initMysql()
	db.Where("_tag = ?", tag).Where("created_at BETWEEN ? AND ?", start, end).Find(&logs)
	findVirtualCard(logs)
}

func findB(logs []Log, mode int) {

	findList := make(map[int][]string)

	findList[1] = []string{
		"GPA.3332-8061-1032-50133",
		"GPA.3343-8449-1696-08846",
		"GPA.3367-2677-3031-67070",
		"GPA.3370-3423-0415-21518",
		"GPA.3385-3139-9658-28862",
		"GPA.3368-1984-4947-91495",
		"GPA.3348-6201-0096-06366",
		"GPA.3315-0197-6676-42233",
	}

	findList[2] = []string{
		"GPA.3398-6448-0667-51725",
		"GPA.3342-6884-7057-96870",
		"GPA.3348-5060-7684-17521",
		"GPA.3354-9905-5073-38297",
		"GPA.3395-8509-4393-66810",
		"GPA.3328-5750-0988-67903",
		"GPA.3311-4067-0686-72736",
		"GPA.3393-4140-3367-90588",
		"GPA.3334-6210-8249-27640",
		"GPA.3365-4459-7803-51106",
		"GPA.3365-3050-1387-28700",
		"GPA.3307-9409-3226-85439",
		"GPA.3316-6801-8979-33427",
		"GPA.3319-2008-1615-85611",
		"GPA.3304-8207-9433-23136",
	}

	findList[3] = []string{
		"GPA.3334-3320-1689-42533",
		"GPA.3355-1072-9149-18470",
		"GPA.3335-6294-4656-03318",
		"GPA.3376-4532-2848-36459",
		"GPA.3344-5194-7350-16669",
		"GPA.3323-3693-6205-89376",
		"GPA.3326-6457-5569-70127",
		"GPA.3389-5572-0398-11580",
		"GPA.3347-8347-3354-48937",
		"GPA.3349-6873-2904-30166",
		"GPA.3326-7032-5994-91330",
		"GPA.3324-6768-9257-84831",
		"GPA.3399-6715-0957-04901",
		"GPA.3304-8691-5642-39613",
		"GPA.3322-6185-9363-88443",
	}

	maps := make(map[string]string)

	for _, log := range logs {
		var info InformationOrder
		err := json.Unmarshal(log.Information, &info)
		if err != nil {
			return
		}
		for _, v := range findList[mode] {
			if v == info.LogInfo.OrderId {
				maps[info.RoleId] = v
			}
		}
	}

	marshal, err := json.Marshal(maps)
	if err != nil {
		return
	}
	fmt.Println(string(marshal))
}

func findA(logs []Log) {

	var infos []Information
	for _, log := range logs {
		var info Information
		err := json.Unmarshal(log.Information, &info)
		if err != nil {
			return
		}
		if info.ActivityId == "71" {
			infos = append(infos, info)
		}
	}

	var ids []string
	var infoss = infos[0:0]
	for _, info := range infos {
		s := strings.Split(info.RewardInfo, ",")
		for _, s2 := range s {
			if s2 == "mode=1" {
				infoss = append(infoss, info)
			}
		}
	}
	for _, info := range infoss {
		s := strings.Split(info.RewardInfo, ",")
		for _, s2 := range s {
			if s2 == "level=2" || s2 == "level=15" {
				ids = append(ids, info.RoleId)
			}
		}
	}

}

func findDeal(logs []Log) {
	deal := dealIds[env]
	var result = make(map[int64][]int64)
	for _, log := range logs {
		var info InformationOrder
		err := json.Unmarshal(log.Information, &info)
		if err != nil {
			return
		}
		dealId := info.LogInfo.DealId
		if utils.IntContains(deal, dealId) > -1 {
			result[dealId] = append(result[dealId], log.RoleId)
		}
	}
	fmt.Println(result)
}

func findVirtualCard(logs []Log) {
	var result []int64
	for _, log := range logs {
		var info VirtualCard
		err := json.Unmarshal(log.Information, &info)
		if err != nil {
			return
		}
		if utils.StringContains(virtualCardIds, info.VirtualCardId) > -1 {
			result = append(result, log.RoleId)
		}
	}
	exportExcel(utils.RemoveRepByMap(result))
}

func exportExcel(values interface{}) {
	file := excelize.NewFile()
	defer func() {
		err := file.Close()
		if err != nil {
			log.Fatal(err)
		}
	}()
	index := file.NewSheet("data")
	file.SetActiveSheet(index)
	style, _ := file.NewStyle(&excelize.Style{
		Alignment: &excelize.Alignment{
			Horizontal: "center",
			Vertical:   "center",
		},
		Border: []excelize.Border{
			{Type: "left", Color: "6e7ea", Style: 1},
			{Type: "top", Color: "e6e7ea", Style: 1},
			{Type: "bottom", Color: "e6e7ea", Style: 1},
			{Type: "right", Color: "e6e7ea", Style: 1},
		},
		Fill: excelize.Fill{Type: "gradient", Color: []string{"#fafbfc", "#fafbfc"}},
		Font: &excelize.Font{Family: "Perpetua", Size: 14},
	})
	newValues := values.([]int64)
	for i, v := range newValues {
		file.SetCellValue(file.GetSheetName(index), "A"+strconv.Itoa(i), strconv.FormatInt(v, 10))
	}
	// 设置行样式
	file.SetColStyle(file.GetSheetName(index), "A", style)
	file.SetColWidth(file.GetSheetName(index), "A", "B", 20)

	if err := file.SaveAs(env + ".xlsx"); err != nil {
		log.Fatal(err)
	}
}
